#include<iostream>
#include<memory>
#include<unordered_map>
#include<vector>
#include<cstdint>
#include<functional>
#include<unistd.h>

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask
{
    private:
        uint64_t _id;           //定时器任务对象id
        uint32_t _timeout;      //定时任务的超时时间
        bool _canceled;         //false - 没有被取消  true - 被取消了不用执行
        TaskFunc _task_cb;      //定时器对象要执行的定时任务
        ReleaseFunc _release;   //用于删除timerwheel中保存到定时器对象信息
    public:

        TimerTask(uint64_t id,uint32_t delay,const TaskFunc &cb):
        _id(id),_timeout(delay),_task_cb(cb),_canceled(false){}

        ~TimerTask()
        {
            if(_canceled==false)
                _task_cb();
            _release();
        }

        void Cancel()
        {
            _canceled = true;
        }

        void SetRelease(const ReleaseFunc &cb)
        {
            _release = cb;
        }

        uint32_t DelayTime()
        {
            return _timeout;
        }
};



class TimerWheel
{
    private:
        using WeakTask = std::weak_ptr<TimerTask>;
        using PtrTask = std::shared_ptr<TimerTask>;
        std::vector<std::vector<PtrTask>> _wheel;
        std::unordered_map<uint64_t,WeakTask> _timers;

        int _tick;          //当前的秒针，走到哪里释放哪里，即执行哪里的任务
        int _capacity;      //表盘最大数量  最大延迟时间

    private:
        void RemoveTimer(uint64_t id)
        {
            auto it = _timers.find(id);
            if(it!=_timers.end())
                _timers.erase(it);
        }

    public:
        TimerWheel():_capacity(60),_tick(0),_wheel(_capacity){}

        void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb)//添加定时任务
        {
            PtrTask pt(new TimerTask(id,delay,cb));
            pt->SetRelease(std::bind(&TimerWheel::RemoveTimer,this,id));

            int pos = (_tick+delay)%_capacity;
            _wheel[pos].push_back(pt);            
            _timers[id] = WeakTask(pt);
        }


        void TimerRefresh(uint64_t id)//刷新延时定时任务
        {
            auto it = _timers.find(id);
            if(it==_timers.end())
                return;
            PtrTask pt = it->second.lock();
            int delay = pt->DelayTime();
            int pos = (_tick+delay)%_capacity;
            _wheel[pos].push_back(pt);
        }

        void TimerCancel(u_int64_t id)
        {
            auto it = _timers.find(id);
            if(it==_timers.end())
                return;
            PtrTask pt = it->second.lock();
            if(pt)pt->Cancel();
        }

        void RunTimerTask()//每秒执行一次
        {
            _tick = (_tick+1)%_capacity; 
            _wheel[_tick].clear();  //清空指定位置的数组，释放数组内的定时器对象的shared_ptr，释放完为0则执行对应的回调
        }

};


class Test
{
    public:
        Test(){std::cout<<"构造"<<std::endl;}
        ~Test(){std::cout<<"析构"<<std::endl;}
};

void DelTest(Test* t)
{
    delete t;
}

int main()
{
    TimerWheel tw;

    Test* t = new Test();

    tw.TimerAdd(204,5,std::bind(DelTest,t));

    for(int i = 0;i<5;i++)
    {
        tw.TimerRefresh(204);
        tw.RunTimerTask();
        std::cout<<"刷新了一下定时任务,5s后销毁"<<std::endl;

        sleep(1);
    }

    tw.TimerCancel(204);

    while(1)
    {
        sleep(1);
        std::cout<<"------------------------\n";
        tw.RunTimerTask();
    }

    return 0;
}